﻿using System;
using System.Data.Objects;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Input;
using WPFDataModel;
using WPFDataModel.DataModel;
using WPFDataModel.ViewModel;

namespace WPFEntityFrameworkTest.DataContext
{
    public class CategoryControlDataContext : NotifyPropertyChangedBase
    {
        #region Static Variables
        #endregion

        #region Member Variables
        public enum EditModes
        {
            Edit,
            Add,
            Delete
        }

        private RelayCommand m_createCategoryCommand;
        private RelayCommand m_saveCategoryCommand;
        private RelayCommand m_deleteProgrammCommand;
        private CategoryViewModel m_categoryViewModel;
        private Category m_currentCategory;
        private EditModes m_editMode;
        #endregion

        #region Propertys
        /// <summary>
        /// Das ViewModel der Category
        /// </summary>
        public CategoryViewModel CategoryViewModel
        {
            get { return m_categoryViewModel; }
            set
            {
                m_categoryViewModel = value;
                OnPropertyChanged(System.Reflection.MethodBase.GetCurrentMethod().Name);
            }
        }

        /// <summary>
        /// Zeigt die aktuell ausgewählte Kategorie
        /// </summary>
        public Category CurrentCategory
        {
            get { return m_currentCategory; }
            set
            {
                m_currentCategory = value;
                OnPropertyChanged(System.Reflection.MethodBase.GetCurrentMethod().Name);
            }
        }

        /// <summary>
        /// gibt an welcher EditMode gerade ausgewählt wurde.
        /// </summary>
        private EditModes EditMode
        {
            get { return m_editMode; }
            set { m_editMode = value; }
        }

        /// <summary>
        /// Command Property um eine Kategorie hinzuzufügen.
        /// </summary>
        public RelayCommand SaveCategoryCommand
        {
            get { return m_saveCategoryCommand; }
        }

        /// <summary>
        /// Command Property um eine Kategorie zu bearbeiten.
        /// </summary>
        public ICommand CreateCategoryCommand
        {
            get { return m_createCategoryCommand; }
        }

        /// <summary>
        /// Löschen der ausgewählten Kategorie
        /// </summary>
        public RelayCommand DeleteCategoryCommand
        {
            get { return m_deleteProgrammCommand; }
        }
        #endregion

        #region Contructors
        /// <summary>
        /// Initiaisieren der Klasse
        /// </summary>
        public CategoryControlDataContext()
        {
            m_categoryViewModel = CategoryViewModel.GetCategoryViewModel();
            m_currentCategory = CategoryViewModel.GetCategoryViewModel().CurrentCategory();

            //Es befinden sich noch keine Elemente in der Liste, dann muss der EditMode add eingestellt werden.
            if (m_currentCategory.Id == 0)
            {
                EditMode = EditModes.Add;
            }

            InitializeCommands();
            InitializeEvents();
        }
        #endregion

        #region Public Functions
        #endregion

        #region Private Functions
        /// <summary>
        /// Initialisieren von Events
        /// </summary>
        private void InitializeEvents()
        {

        }
        #endregion

        #region Commands
        /// <summary>
        /// Initialisieren der Commands
        /// </summary>
        private void InitializeCommands()
        {
            m_createCategoryCommand = new RelayCommand(param => CreateCategory());
            m_saveCategoryCommand = new RelayCommand(param => SaveCategory());
            m_deleteProgrammCommand = new RelayCommand(param => DeleteCategory());
        }

        /// <summary>
        /// Erstellen einer neuen Kategorie
        /// </summary>
        private void CreateCategory()
        {
            //Den Modus umstellen auf Edit.
            EditMode = EditModes.Add;
            //ERstellen einer neuen Kategorie, die später beim Speichern der Liste hinzugefügt wird.
            CurrentCategory = new Category();
        }

        /// <summary>
        /// Speichern der Kategorie
        /// </summary>
        private void SaveCategory()
        {
            //Anhand des aktuellen EditModes festlegen welche Aktuelle Category dargestellt werden soll.
            switch (EditMode)
            {
                case EditModes.Add:
                    CategoryViewModel.GetCategoryViewModel().AddCategory(CurrentCategory);
                    EditMode = EditModes.Edit;
                    break;
                case EditModes.Edit:
                    //Hier werden die Änderungen die vorgenommen wurden auch "übertragen" ist notwendig durch "MergeOption.NoTracking" die beim Erstellen des Fensters gesetzt werden.
                    CategoryViewModel.GetCategoryViewModel().CategoriesObjectSet.ApplyCurrentValues(CurrentCategory);
                    break;
            }

            CategoryViewModel.GetCategoryViewModel().SaveCategory();
        }

        /// <summary>
        /// Löschen der Ausgewählten Kategorie
        /// </summary>
        private void DeleteCategory()
        {
            //Setzten des aktuellen Modus, wird benötigt aufgrund der "SelectionChangedMethod" 
            EditMode = EditModes.Delete;
            //Löschen der akutellen Kategorie
            CategoryViewModel.DeleteSelectedCategories();

            //Wenn sich keine elemente mehr in der Liste befinden, muss der EditMode Add eingestellt werden.
            if (CategoryViewModel.Categories.Count == 0)
            {
                EditMode = EditModes.Add;
            }
        }
        #endregion

        #region Events
        /// <summary>
        /// Selection Changes Event der Kategorienliste abfangen.
        /// Abfangen von Events per MVVM Pattern, dafür wird Expression Blend benötigt.
        /// http://webenliven-space.de/dotnetblog/post/2010/07/27/Das-MVVM-und-Events.aspx
        /// </summary>
        public void SelectionChangedMethod(object sender, SelectionChangedEventArgs e)
        {
            //Es muss aufgepasst werden, denn SelectionChanged wird auch beim Hinzufügen eines neuen Wertes aufgerufen und darf nicht immer "genutzt" werden, da es sonst zu einem Fehler kommt.
            if (EditMode == EditModes.Edit || CategoryViewModel.CurrentCategory().Id != 0)
            {
                //http://stackoverflow.com/questions/803022/changing-entities-in-the-entityframework?tab=votes#tab-top
                //Einstellen das Änderungen nicht angezeigt werden in der Oberfläche
                CategoryViewModel.GetCategoryViewModel().CategoriesObjectSet.MergeOption = MergeOption.NoTracking;
                //Die ID muss extra ausgeselen werden wenn dies bei First gemacht wird, dann kommt es zu einem Fehler!
                int id = CategoryViewModel.GetCategoryViewModel().CurrentCategory().Id;
                //auslesen des Obejektes was bearbeitet werden soll und mit Hilfe der NoTracking Option werden Änderungen 
                //auch nicht in der Originalliste angezeigt und erst dann wirklich im Objekt gespeichert wenn Save aufgerufen wird.
                CurrentCategory = CategoryViewModel.GetCategoryViewModel().CategoriesObjectSet.First(cat => cat.Id == id);
                EditMode = EditModes.Edit;
            }
            else
            {
                //Sobald jmd in der Liste einen neuen Wert auswählt, befindet sich diese im EditMode
                //Editmode heißt das man rechts in den Details die Kategorie bearbeiten kann, aber die Änderungen nicht life in der Liste sieht sondern erst wenn gespeichert wird.
                EditMode = EditModes.Edit;    
            }
        }
        #endregion
    }
}
